package Dynamic_Programming.package_01;
/*
* 背包大小：sum/2
* 物品  1  2  3  sum/2
*  0
*  1
*  2
*  3
确定dp数组（dp table）以及下标的含义
    dp[i][j]
确定递推公式
    不放物品（j<val[i]）： dp[i][j]=dp[i-1][j]
    放物品：dp[i][j]=max(dp[i-1][j],dp[i-1][j-val[i]]+val[i])
dp数组如何初始化
    第一列都是0
    第一行根据物品0的大小来
确定遍历顺序
举例推导dp数组
* */
public class lc416 {
    public static void main(String[] args) {
        int[] nums=new int[]{1,5,11,5};
        canPartition(nums);
    }
    public static boolean canPartition(int[] nums) {

        int sum=0;
        for (int val:nums
             ) {
            sum+=val;
        }
        if(sum % 2 == 1)
            return false;
        int[][] dp=new int[nums.length][sum/2+1];
        //初始化
        for (int i = 0; i < nums.length ; i++) {
            //列初始化
            dp[i][0]=0;
        }
        for (int i = 0; i <sum/2+1 ; i++) {
            //行初始化
            if(i<nums[0]){
                dp[0][i]=0;
            }else {
                dp[0][i]=nums[0];
            }
        }
        for (int i = 1; i <nums.length ; i++) {
            for (int j = 0; j <sum/2+1 ; j++) {
                if(j<nums[i]){
                    dp[i][j]=dp[i-1][j];
                }else {
                    dp[i][j]=Math.max(dp[i-1][j],dp[i-1][j-nums[i]]+nums[i]);
                }
            }
        }
        for (int i = 0; i <nums.length ; i++) {
            for (int j = 0; j <sum/2+1 ; j++) {
                System.out.print(dp[i][j] + " ");
                if(j==sum/2) System.out.println();
            }
        }
        if(dp[nums.length-1][sum/2]==sum/2)
        return true;
        return false;
    }
    public static boolean can(int[] nums){
        //答案
        if(nums == null || nums.length == 0) return false;
        int n = nums.length;
        int sum = 0;
        for(int num : nums) {
            sum += num;
        }
        //总和为奇数，不能平分
        if(sum % 2 != 0) return false;
        int target = sum / 2;
        int[] dp = new int[target + 1];
        for(int i = 0; i < n; i++) {
            for(int j = target; j >= nums[i]; j--) {
                //物品 i 的重量是 nums[i]，其价值也是 nums[i]
                dp[j] = Math.max(dp[j], dp[j - nums[i]] + nums[i]);
            }

            //剪枝一下，每一次完成內層的for-loop，立即檢查是否dp[target] == target，優化時間複雜度（26ms -> 20ms）
            if(dp[target] == target)
                return true;
        }
        return dp[target] == target;
    }
}
